#include "codegen.h"

int n_labels = 0;
static char* code;

char * getreg(int lvl)
{
  switch(lvl)
    {
    case 1 : return "%eax";
      break;
    case 2 : return "%ebx";
      break;
    case 3 : return "%ecx";
      break;
    case 4 : return "%edx";
      break;
    case 5 : return "%esi";
      break;
    case 6 : return "%edi";
      break;
      //default : 
    }
}

char * gen_expr(struct tree * t, int reglvl)
{
  char *str;
  if(t->l == NULL || t->r == NULL)
    perror("Erreur dans gen_expr() : visite d'une feuille\n");
  if(t->l->height == 1)
    {
      // Feuille à gauche - Feuille à droite
      if(t->r->height == 1)
	{
	  str = concat( gen_leaf(t->l, reglvl), gen_leaf(t->r, reglvl+1), NULL );
	}
      // Feuille à gauche - expr à droite
      else
	{
	  str = concat( gen_expr(t->r, reglvl), gen_leaf(t->l, reglvl+1), NULL );
	}
    }
      // expr à gauche - Feuille à droite
  else if(t->r->height == 1)
    {
      str = concat( gen_expr(t->l, reglvl), gen_leaf(t->r, reglvl+1), NULL );
    }
      // expr à gauche - expr à droite
  else
    {
      if(t->l->height < t->r->height)
	{
	  str = concat( gen_expr(t->l, reglvl+1), gen_expr(t->r, reglvl), NULL );
	}
      else
	{
	  str = concat( gen_expr(t->l, reglvl), gen_expr(t->r, reglvl+1), NULL );
	}
    }


  switch(t->op)
    {
    case PLUS : 
      return concat(str, "\taddl\t", getreg(reglvl+1), ", ", getreg(reglvl), "\n", NULL);
      break;
    case MOINS :
      return concat(str, "\tsubl\t", getreg(reglvl), ", ", getreg(reglvl+1), "\n", "\tmovl\t", getreg(reglvl+1), ", ", getreg(reglvl), "\n", NULL);
      break;
    case FOIS :
      return concat(str, "\tmull\t", getreg(reglvl+1), ", ", getreg(reglvl), "\n", NULL);
      break;
    case DIVISE :
      return concat(str, "\tmovl\t%eax, ", getreg(reglvl+2), "\n\tmovl\t", getreg(reglvl), ", %eax\n\tidivl\t", getreg(reglvl+1), "\n\tmovl\t%eax, ", getreg(reglvl), "\n\tmovl\t", getreg(reglvl+2), ", %eax\n", NULL);
      break;
    case MODULO :
      
    }
  return str;
}

char * gen_leaf(struct tree * t, int reglvl)
{
  if(t->op == ENTIER)
    {
      // Changer le 10 (à formaliser)
      char cst[10];
      printf("node_val : %d\n", t->node_val);
      sprintf(cst, "%d", t->node_val);
      return concat("\tmovl\t", "$", cst, ", ", getreg(reglvl), "\n", NULL); 
      
      /* Faire en sorte que gen_expr n'appelle gen_leaf que si feuille-feuille, pour avoir 2 movl. Ou bien il l'appelle aussi mais gen_leaf génère autre chose selon que.*/
    }
  /*  if(t->op == ID)
    {

    }*/
}

char * gen_if(char *expr, char *instr)
{
  char label[10];
  sprintf(label, "%d", n_labels);
  char *str = concat(expr,
		     "\tcmpl\t$0, %eax\n\tjz\t.label",
		     label,
		     "\n",
		     // instructions
		     instr,
		     // label 1
		     ".label",
		     label,
		     ":\n",
		     NULL);
  n_labels++;
  return str;
}

char *concat(char *mot, ...)
{
  va_list chaines;

  char *x, *ou, *res;
  int longueur;

  longueur = strlen(mot);
  va_start(chaines, mot);

  while(x = va_arg(chaines, char*))
    {
      longueur += strlen(x);
    }

  va_end(chaines);

  ou = res = (char*)malloc(1+longueur);

  strcpy(ou, mot);
  ou += strlen(mot);
  va_start(chaines, mot);

  while(x = va_arg(chaines, char*))
    {
      strcpy(ou, x);
      ou += strlen(x);
    }

  va_end(chaines);
  return res;
}

void dump(char* code)
{
  printf("Ecriture dans le fichier assembleur...\n");
  FILE *fic = fopen("ass.s", "w");
  fputs(code, fic);
}
